home *** CD-ROM | disk | FTP | other *** search
/ Amiga Games Extra 1996 September / Amiga Games Extra CD-ROM 9-1996.iso / userbox / publicdomain / vim-4.2 / src / fileio.c < prev    next >
C/C++ Source or Header  |  1996-06-17  |  49KB  |  1,991 lines

  1. /* vi:set ts=4 sw=4:
  2.  *
  3.  * VIM - Vi IMproved        by Bram Moolenaar
  4.  *
  5.  * Do ":help uganda"  in Vim to read copying and usage conditions.
  6.  * Do ":help credits" in Vim to see a list of people who contributed.
  7.  */
  8.  
  9. /*
  10.  * fileio.c: read from and write to a file
  11.  */
  12.  
  13. #if defined MSDOS  ||  defined WIN32
  14. # include <io.h>        /* for lseek(), must be before vim.h */
  15. #endif
  16.  
  17. #include "vim.h"
  18. #include "globals.h"
  19. #include "proto.h"
  20. #include "option.h"
  21. #ifdef HAVE_FCNTL_H
  22. # include <fcntl.h>
  23. #endif
  24.  
  25. #ifdef LATTICE
  26. # include <proto/dos.h>        /* for Lock() and UnLock() */
  27. #endif
  28.  
  29. #define BUFSIZE        8192            /* size of normal write buffer */
  30. #define SBUFSIZE    256                /* size of emergency write buffer */
  31.  
  32. #ifdef VIMINFO
  33. static void check_marks_read __ARGS((void));
  34. #endif
  35. static void msg_add_fname __ARGS((BUF *, char_u *));
  36. static int msg_add_textmode __ARGS((int));
  37. static void msg_add_lines __ARGS((int, long, long));
  38. static int  write_buf __ARGS((int, char_u *, int));
  39.  
  40. static linenr_t    write_no_eol_lnum = 0;     /* non-zero lnum when last line of
  41.                                            next binary write should not have
  42.                                            an eol */
  43.  
  44.     void
  45. filemess(buf, name, s)
  46.     BUF            *buf;
  47.     char_u        *name;
  48.     char_u        *s;
  49. {
  50.     msg_add_fname(buf, name);        /* put file name in IObuff with quotes */
  51.     STRCAT(IObuff, s);
  52.     /*
  53.      * For the first message may have to start a new line.
  54.      * For further ones overwrite the previous one, reset msg_scroll before
  55.      * calling filemess().
  56.      */
  57.     msg_start();
  58.     msg_outtrans(IObuff);
  59.     stop_highlight();
  60.     msg_clr_eos();
  61.     flushbuf();
  62. }
  63.  
  64. /*
  65.  * Read lines from file 'fname' into the buffer after line 'from'.
  66.  *
  67.  * 1. We allocate blocks with lalloc, as big as possible.
  68.  * 2. Each block is filled with characters from the file with a single read().
  69.  * 3. The lines are inserted in the buffer with ml_append().
  70.  *
  71.  * (caller must check that fname != NULL)
  72.  *
  73.  * lines_to_skip is the number of lines that must be skipped
  74.  * lines_to_read is the number of lines that are appended
  75.  * When not recovering lines_to_skip is 0 and lines_to_read MAXLNUM.
  76.  *
  77.  * return FAIL for failure, OK otherwise
  78.  */
  79.     int
  80. readfile(fname, sfname, from, newfile, lines_to_skip, lines_to_read, filtering)
  81.     char_u           *fname;
  82.     char_u           *sfname;
  83.     linenr_t        from;
  84.     int                newfile;
  85.     linenr_t        lines_to_skip;
  86.     linenr_t        lines_to_read;
  87.     int                filtering;
  88. {
  89.     int                 fd;
  90.     register char_u     c;
  91.     register linenr_t    lnum = from;
  92.     register char_u     *ptr = NULL;            /* pointer into read buffer */
  93.     register char_u        *buffer = NULL;            /* read buffer */
  94.     char_u                *new_buffer = NULL;        /* init to shut up gcc */
  95.     char_u                *line_start = NULL;        /* init to shut up gcc */
  96.     colnr_t                len;
  97.     register long        size;
  98.     register char_u        *p;
  99.     long                filesize = 0;
  100.     int                    split = 0;                /* number of split lines */
  101. #define UNKNOWN        0x0fffffff                    /* file size is unknown */
  102.     linenr_t            linecnt = curbuf->b_ml.ml_line_count;
  103.     int                 error = FALSE;            /* errors encountered */
  104.     int                    tx_error = FALSE;        /* textmode, but no CR */
  105.     long                linerest = 0;            /* remaining characters in line */
  106.     int                    firstpart = TRUE;        /* reading first part */
  107. #ifdef UNIX
  108.     int                    perm;
  109. #endif
  110.     int                    textmode;                /* accept CR-LF linebreak */
  111.     struct stat            st;
  112.     int                    file_readonly;
  113.     linenr_t            skip_count = lines_to_skip;
  114.     linenr_t            read_count = lines_to_read;
  115.     int                    msg_save = msg_scroll;
  116.     linenr_t            read_no_eol_lnum = 0;     /* non-zero lnum when last
  117.                                                    line of last read was
  118.                                                    missing the eol */
  119.  
  120.  
  121.     /*
  122.      * If there is no file name yet, use the one for the read file.
  123.      * b_notedited is set to reflect this.
  124.      * Don't do this for a read from a filter.
  125.      * Only do this when 'cpoptions' contains the 'f' flag.
  126.      */
  127.     if (curbuf->b_filename == NULL && !filtering &&
  128.                                         vim_strchr(p_cpo, CPO_FNAMER) != NULL)
  129.     {
  130.         if (setfname(fname, sfname, FALSE) == OK)
  131.             curbuf->b_notedited = TRUE;
  132.     }
  133.  
  134.     if (shortmess(SHM_OVER) || curbuf->b_help)
  135.         msg_scroll = FALSE;        /* overwrite previous file message */
  136.     else
  137.         msg_scroll = TRUE;        /* don't overwrite previous file message */
  138.     if (sfname == NULL)
  139.         sfname = fname;
  140.     /*
  141.      * For Unix: Use the short filename whenever possible.
  142.      * Avoids problems with networks and when directory names are changed.
  143.      * Don't do this for MS-DOS, a "cd" in a sub-shell may have moved us to
  144.      * another directory, which we don't detect.
  145.      */
  146. #if defined(UNIX) || defined(__EMX__)
  147.     if (!did_cd)
  148.         fname = sfname;
  149. #endif
  150.  
  151. #ifdef UNIX
  152.     /*
  153.      * On Unix it is possible to read a directory, so we have to
  154.      * check for it before the open().
  155.      */
  156.     perm = getperm(fname);
  157. # ifdef _POSIX_SOURCE
  158.     if (perm >= 0 && !S_ISREG(perm)                     /* not a regular file ... */
  159. #  ifdef S_ISFIFO
  160.                   && !S_ISFIFO(perm)                /* ... or fifo or socket */
  161. #  endif
  162.                                            )
  163. # else
  164.     if (perm >= 0 && (perm & S_IFMT) != S_IFREG        /* not a regular file ... */
  165. #  ifdef S_IFIFO
  166.                   && (perm & S_IFMT) != S_IFIFO        /* ... or fifo ... */
  167. #  endif
  168. #  ifdef S_IFSOCK
  169.                   && (perm & S_IFMT) != S_IFSOCK    /* ... or socket */
  170. #  endif
  171.                                             )
  172. # endif
  173.     {
  174. # ifdef _POSIX_SOURCE
  175.         if (S_ISDIR(perm))
  176. # else
  177.         if ((perm & S_IFMT) == S_IFDIR)
  178. # endif
  179.             filemess(curbuf, fname, (char_u *)"is a directory");
  180.         else
  181.             filemess(curbuf, fname, (char_u *)"is not a file");
  182.         msg_scroll = msg_save;
  183.         return FAIL;
  184.     }
  185. #endif
  186.  
  187.     /*
  188.      * When opening a new file we take the readonly flag from the file.
  189.      * Default is r/w, can be set to r/o below.
  190.      * Don't reset it when in readonly mode
  191.      */
  192.     if (newfile && !readonlymode)            /* default: set file not readonly */
  193.         curbuf->b_p_ro = FALSE;
  194.  
  195.     if (newfile)
  196.     {
  197.         if (stat((char *)fname, &st) >= 0)    /* remember time of file */
  198.         {
  199.             curbuf->b_mtime = st.st_mtime;
  200.             curbuf->b_mtime_read = st.st_mtime;
  201. #ifdef UNIX
  202.             /*
  203.              * Set the protection bits of the swap file equal to the original
  204.              * file. This makes it possible for others to read the name of the
  205.              * original file from the swapfile.
  206.              */
  207.             if (curbuf->b_ml.ml_mfp->mf_fname != NULL)
  208.                 (void)setperm(curbuf->b_ml.ml_mfp->mf_fname,
  209.                                                   (st.st_mode & 0777) | 0600);
  210. #endif
  211.         }
  212.         else
  213.         {
  214.             curbuf->b_mtime = 0;
  215.             curbuf->b_mtime_read = 0;
  216.         }
  217.     }
  218.  
  219. /*
  220.  * for UNIX: check readonly with perm and access()
  221.  * for MSDOS and Amiga: check readonly by trying to open the file for writing
  222.  */
  223.     file_readonly = FALSE;
  224. #if defined(UNIX) || defined(DJGPP) || defined(__EMX__)
  225.     if (
  226. # ifdef UNIX
  227.         !(perm & 0222) ||
  228. # endif
  229.                             access((char *)fname, W_OK))
  230.         file_readonly = TRUE;
  231.     fd = open((char *)fname, O_RDONLY | O_EXTRA);
  232. #else
  233.     if (!newfile || readonlymode || (fd =
  234.                                    open((char *)fname, O_RDWR | O_EXTRA)) < 0)
  235.     {
  236.         file_readonly = TRUE;
  237.         fd = open((char *)fname, O_RDONLY | O_EXTRA);    /* try to open ro */
  238.     }
  239. #endif
  240.  
  241.     if (fd < 0)                     /* cannot open at all */
  242.     {
  243. #ifndef UNIX
  244.         int        isdir_f;
  245. #endif
  246.         msg_scroll = msg_save;
  247. #ifndef UNIX
  248.     /*
  249.      * On MSDOS and Amiga we can't open a directory, check here.
  250.      */
  251.         isdir_f = (mch_isdir(fname));
  252.         /* replace with short name now, for the messages */
  253.         if (!did_cd)
  254.             fname = sfname;
  255.         if (isdir_f)
  256.             filemess(curbuf, fname, (char_u *)"is a directory");
  257.         else
  258. #endif
  259.             if (newfile)
  260.             {
  261. #ifdef UNIX
  262.                 if (perm < 0)
  263. #endif
  264.                 {
  265.                     filemess(curbuf, fname, (char_u *)"[New File]");
  266. #ifdef AUTOCMD
  267.                     apply_autocmds(EVENT_BUFNEWFILE, fname, fname);
  268. #endif
  269.                     return OK;        /* a new file is not an error */
  270.                 }
  271. #ifdef UNIX
  272.                 else
  273.                     filemess(curbuf, fname, (char_u *)"[Permission Denied]");
  274. #endif
  275.             }
  276.  
  277.         return FAIL;
  278.     }
  279.  
  280.     /*
  281.      * Only set the 'ro' flag for readonly files the first time they are
  282.      * loaded.
  283.      * Help files always get readonly mode
  284.      */
  285.     if ((newfile && file_readonly) || curbuf->b_help)
  286.         curbuf->b_p_ro = TRUE;
  287.  
  288.     if (newfile)
  289.         curbuf->b_p_eol = TRUE;
  290.  
  291. #ifndef UNIX
  292.     /* replace with short name now, for the messages */
  293.     if (!did_cd)
  294.         fname = sfname;
  295. #endif
  296.     ++no_wait_return;                            /* don't wait for return yet */
  297.  
  298.     /*
  299.      * Set '[ mark to the line above where the lines go (line 1 if zero).
  300.      */
  301.     curbuf->b_op_start.lnum = ((from == 0) ? 1 : from);
  302.     curbuf->b_op_start.col = 0;
  303.  
  304. #ifdef AUTOCMD
  305.     {
  306.         int    m = msg_scroll;
  307.         int n = msg_scrolled;
  308.  
  309.         /*
  310.          * The output from the autocommands should not overwrite anything and
  311.          * should not be overwritten: Set msg_scroll, restore its value if no
  312.          * output was done.
  313.          */
  314.         msg_scroll = TRUE;
  315.         if (filtering)
  316.             apply_autocmds(EVENT_FILTERREADPRE, NULL, fname);
  317.         else if (newfile)
  318.             apply_autocmds(EVENT_BUFREADPRE, NULL, fname);
  319.         else
  320.             apply_autocmds(EVENT_FILEREADPRE, fname, fname);
  321.         if (msg_scrolled == n)
  322.             msg_scroll = m;
  323.     }
  324. #endif
  325.  
  326.     if (!recoverymode && !filtering)
  327.         filemess(curbuf, fname, (char_u *)"");    /* show that we are busy */
  328.  
  329.     msg_scroll = FALSE;                            /* overwrite the file message */
  330.  
  331.     /*
  332.      * Set textmode now, before the "retry" caused by 'textauto' and after the
  333.      * autocommands, that may reset it.
  334.      */
  335.     textmode = curbuf->b_p_tx;
  336.  
  337. retry:
  338.     while (!error && !got_int)
  339.     {
  340.         /*
  341.          * We allocate as much space for the file as we can get, plus
  342.          * space for the old line plus room for one terminating NUL.
  343.          * The amount is limited by the fact that read() only can read
  344.          * upto max_unsigned characters (and other things).
  345.          */
  346. #if SIZEOF_INT <= 2
  347.         if (linerest >= 0x7ff0)
  348.         {
  349.             ++split;
  350.             *ptr = NL;                /* split line by inserting a NL */
  351.             size = 1;
  352.         }
  353.         else
  354. #endif
  355.         {
  356. #if SIZEOF_INT > 2
  357.             size = 0x10000L;                /* use buffer >= 64K */
  358. #else
  359.             size = 0x7ff0L - linerest;        /* limit buffer to 32K */
  360. #endif
  361.  
  362.             for ( ; size >= 10; size >>= 1)
  363.             {
  364.                 if ((new_buffer = lalloc((long_u)(size + linerest + 1), FALSE)) != NULL)
  365.                     break;
  366.             }
  367.             if (new_buffer == NULL)
  368.             {
  369.                 do_outofmem_msg();
  370.                 error = TRUE;
  371.                 break;
  372.             }
  373.             if (linerest)        /* copy characters from the previous buffer */
  374.                 vim_memmove(new_buffer, ptr - linerest, (size_t)linerest);
  375.             vim_free(buffer);
  376.             buffer = new_buffer;
  377.             ptr = buffer + linerest;
  378.             line_start = buffer;
  379.             
  380.             if ((size = read(fd, (char *)ptr, (size_t)size)) <= 0)
  381.             {
  382.                 if (size < 0)                /* read error */
  383.                     error = TRUE;
  384.                 break;
  385.             }
  386.             filesize += size;                /* count the number of characters */
  387.  
  388.             /*
  389.              * when reading the first part of a file: guess EOL type
  390.              */
  391.             if (firstpart && p_ta)
  392.             {
  393.                 for (p = ptr; p < ptr + size; ++p)
  394.                     if (*p == NL)
  395.                     {
  396.                         if (p > ptr && p[-1] == CR)    /* found CR-NL */
  397.                             textmode = TRUE;
  398.                         else                        /* found a single NL */
  399.                             textmode = FALSE;
  400.                             /* if editing a new file: may set p_tx */
  401.                         if (newfile)
  402.                             curbuf->b_p_tx = textmode;
  403.                         break;
  404.                     }
  405.             }
  406.         }
  407.  
  408.         firstpart = FALSE;
  409.  
  410.         /*
  411.          * This loop is executed once for every character read.
  412.          * Keep it fast!
  413.          */
  414.         --ptr;
  415.         while (++ptr, --size >= 0)
  416.         {
  417.             if ((c = *ptr) != NUL && c != NL)    /* catch most common case */
  418.                 continue;
  419.             if (c == NUL)
  420.                 *ptr = NL;        /* NULs are replaced by newlines! */
  421.             else
  422.             {
  423.                 if (skip_count == 0)
  424.                 {
  425.                     *ptr = NUL;        /* end of line */
  426.                     len = ptr - line_start + 1;
  427.                     if (textmode)
  428.                     {
  429.                         if (ptr[-1] == CR)    /* remove CR */
  430.                         {
  431.                             ptr[-1] = NUL;
  432.                             --len;
  433.                         }
  434.                         /*
  435.                          * Reading in textmode, but no CR-LF found!
  436.                          * When 'textauto' set, delete all the lines read so
  437.                          * far and start all over again.
  438.                          * Otherwise give an error message later.
  439.                          */
  440.                         else if (!tx_error)
  441.                         {
  442.                             if (p_ta && lseek(fd, 0L, SEEK_SET) == 0)
  443.                             {
  444.                                 while (lnum > from)
  445.                                     ml_delete(lnum--, FALSE);
  446.                                 textmode = FALSE;
  447.                                 if (newfile)
  448.                                     curbuf->b_p_tx = FALSE;
  449.                                 linerest = 0;
  450.                                 filesize = 0;
  451.                                 skip_count = lines_to_skip;
  452.                                 read_count = lines_to_read;
  453.                                 goto retry;
  454.                             }
  455.                             else
  456.                                 tx_error = TRUE;
  457.                         }
  458.                     }
  459.                     if (ml_append(lnum, line_start, len, newfile) == FAIL)
  460.                     {
  461.                         error = TRUE;
  462.                         break;
  463.                     }
  464.                     ++lnum;
  465.                     if (--read_count == 0)
  466.                     {
  467.                         error = TRUE;        /* break loop */
  468.                         line_start = ptr;    /* nothing left to write */
  469.                         break;
  470.                     }
  471.                 }
  472.                 else
  473.                     --skip_count;
  474.                 line_start = ptr + 1;
  475.             }
  476.         }
  477.         linerest = ptr - line_start;
  478.         mch_breakcheck();
  479.     }
  480.  
  481.     /* not an error, max. number of lines reached */
  482.     if (error && read_count == 0)
  483.         error = FALSE;
  484.  
  485.     /*
  486.      * If we get EOF in the middle of a line, note the fact and
  487.      * complete the line ourselves.
  488.      * In textmode ignore a trailing CTRL-Z, unless 'binary' set.
  489.      */
  490.     if (!error && !got_int && linerest != 0 &&
  491.             !(!curbuf->b_p_bin && textmode &&
  492.                     *line_start == Ctrl('Z') && ptr == line_start + 1))
  493.     {
  494.         if (newfile)                /* remember for when writing */
  495.             curbuf->b_p_eol = FALSE;
  496.         *ptr = NUL;
  497.         if (ml_append(lnum, line_start,
  498.                         (colnr_t)(ptr - line_start + 1), newfile) == FAIL)
  499.             error = TRUE;
  500.         else
  501.             read_no_eol_lnum = ++lnum;
  502.     }
  503.     if (lnum != from && !newfile)    /* added at least one line */
  504.         CHANGED;
  505.  
  506.     close(fd);                        /* errors are ignored */
  507.     vim_free(buffer);
  508.  
  509.     --no_wait_return;                /* may wait for return now */
  510.  
  511.     /* in recovery mode everything but autocommands are skipped */
  512.     if (!recoverymode)
  513.     {
  514.  
  515.         /* need to delete the last line, which comes from the empty buffer */
  516.         if (newfile && !(curbuf->b_ml.ml_flags & ML_EMPTY))
  517.         {
  518.             ml_delete(curbuf->b_ml.ml_line_count, FALSE);
  519.             --linecnt;
  520.         }
  521.         linecnt = curbuf->b_ml.ml_line_count - linecnt;
  522.         if (filesize == 0)
  523.             linecnt = 0;
  524.         if (!newfile)
  525.             mark_adjust(from + 1, MAXLNUM, (long)linecnt, 0L);
  526.  
  527.         if (got_int)
  528.         {
  529.             filemess(curbuf, fname, e_interr);
  530.             msg_scroll = msg_save;
  531. #ifdef VIMINFO
  532.             check_marks_read();
  533. #endif /* VIMINFO */
  534.             return OK;            /* an interrupt isn't really an error */
  535.         }
  536.  
  537.         if (!filtering)
  538.         {
  539.             msg_add_fname(curbuf, fname);    /* fname in IObuff with quotes */
  540.             c = FALSE;
  541.  
  542. #ifdef UNIX
  543. # ifdef S_ISFIFO
  544.             if (S_ISFIFO(perm))                        /* fifo or socket */
  545.             {
  546.                 STRCAT(IObuff, "[fifo/socket]");
  547.                 c = TRUE;
  548.             }
  549. # else
  550. #  ifdef S_IFIFO
  551.             if ((perm & S_IFMT) == S_IFIFO)            /* fifo */
  552.             {
  553.                 STRCAT(IObuff, "[fifo]");
  554.                 c = TRUE;
  555.             }
  556. #  endif
  557. #  ifdef S_IFSOCK
  558.             if ((perm & S_IFMT) == S_IFSOCK)        /* or socket */
  559.             {
  560.                 STRCAT(IObuff, "[socket]");
  561.                 c = TRUE;
  562.             }
  563. #  endif
  564. # endif
  565. #endif
  566.             if (curbuf->b_p_ro)
  567.             {
  568.                 STRCAT(IObuff, shortmess(SHM_RO) ? "[RO]" : "[readonly]");
  569.                 c = TRUE;
  570.             }
  571.             if (read_no_eol_lnum)
  572.             {
  573.                 STRCAT(IObuff, shortmess(SHM_LAST) ? "[noeol]" :
  574.                                                     "[Incomplete last line]");
  575.                 c = TRUE;
  576.             }
  577.             if (tx_error)
  578.             {
  579.                 STRCAT(IObuff, "[CR missing]");
  580.                 c = TRUE;
  581.             }
  582.             if (split)
  583.             {
  584.                 STRCAT(IObuff, "[long lines split]");
  585.                 c = TRUE;
  586.             }
  587.             if (error)
  588.             {
  589.                 STRCAT(IObuff, "[READ ERRORS]");
  590.                 c = TRUE;
  591.             }
  592.             if (msg_add_textmode(textmode))
  593.                 c = TRUE;
  594.             msg_add_lines(c, (long)linecnt, filesize);
  595.             msg_trunc(IObuff);
  596.         }
  597.  
  598.         if (error && newfile)    /* with errors we should not write the file */
  599.             curbuf->b_p_ro = TRUE;
  600.  
  601.         u_clearline();        /* cannot use "U" command after adding lines */
  602.  
  603.         if (from < curbuf->b_ml.ml_line_count)
  604.         {
  605.             curwin->w_cursor.lnum = from + 1;    /* cursor at first new line */
  606.             beginline(TRUE);                    /* on first non-blank */
  607.         }
  608.  
  609.         /*
  610.          * Set '[ and '] marks to the newly read lines.
  611.          */
  612.         curbuf->b_op_start.lnum = from + 1;
  613.         curbuf->b_op_start.col = 0;
  614.         curbuf->b_op_end.lnum = from + linecnt;
  615.         curbuf->b_op_end.col = 0;
  616.     }
  617.     msg_scroll = msg_save;
  618.  
  619. #ifdef AUTOCMD
  620.     {
  621.         int    m = msg_scroll;
  622.         int n = msg_scrolled;
  623.  
  624.         /*
  625.          * Trick: We remember if the last line of the read didn't have
  626.          * an eol for when writing it again.  This is required for
  627.          * ":autocmd FileReadPost *.gz set bin|%!gunzip" to work.
  628.          */
  629.         write_no_eol_lnum = read_no_eol_lnum;
  630.  
  631.         /*
  632.          * The output from the autocommands should not overwrite anything and
  633.          * should not be overwritten: Set msg_scroll, restore its value if no
  634.          * output was done.
  635.          */
  636.         msg_scroll = TRUE;
  637.         if (filtering)
  638.             apply_autocmds(EVENT_FILTERREADPOST, NULL, fname);
  639.         else if (newfile)
  640.             apply_autocmds(EVENT_BUFREADPOST, NULL, fname);
  641.         else
  642.             apply_autocmds(EVENT_FILEREADPOST, fname, fname);
  643.         if (msg_scrolled == n)
  644.             msg_scroll = m;
  645.  
  646.         write_no_eol_lnum = 0;
  647.     }
  648. #endif
  649.  
  650. #ifdef VIMINFO
  651.     check_marks_read();
  652. #endif /* VIMINFO */
  653.  
  654.     if (recoverymode && error)
  655.         return FAIL;
  656.     return OK;
  657. }
  658.  
  659. #ifdef VIMINFO
  660.     static void
  661. check_marks_read()
  662. {
  663.     if (!curbuf->b_marks_read && get_viminfo_parameter('\'') > 0)
  664.     {
  665.         read_viminfo(NULL, FALSE, TRUE, FALSE);
  666.         curbuf->b_marks_read = TRUE;
  667.     }
  668. }
  669. #endif /* VIMINFO */
  670.  
  671. /*
  672.  * writeit - write to file 'fname' lines 'start' through 'end'
  673.  *
  674.  * We do our own buffering here because fwrite() is so slow.
  675.  *
  676.  * If forceit is true, we don't care for errors when attempting backups (jw).
  677.  * In case of an error everything possible is done to restore the original file.
  678.  * But when forceit is TRUE, we risk loosing it.
  679.  * When reset_changed is TRUE and start == 1 and end ==
  680.  * curbuf->b_ml.ml_line_count, reset curbuf->b_changed.
  681.  *
  682.  * This function must NOT use NameBuff (because it's called by autowrite()).
  683.  *
  684.  * return FAIL for failure, OK otherwise
  685.  */
  686.     int
  687. buf_write(buf, fname, sfname, start, end, append, forceit,
  688.                                                       reset_changed, filtering)
  689.     BUF                *buf;
  690.     char_u            *fname;
  691.     char_u            *sfname;
  692.     linenr_t        start, end;
  693.     int                append;
  694.     int                forceit;
  695.     int                reset_changed;
  696.     int                filtering;
  697. {
  698.     int                 fd;
  699.     char_u               *backup = NULL;
  700.     char_u               *ffname;
  701. #ifdef AUTOCMD
  702.     BUF                   *save_buf;
  703. #endif
  704.     register char_u       *s;
  705.     register char_u       *ptr;
  706.     register char_u        c;
  707.     register int        len;
  708.     register linenr_t    lnum;
  709.     long                nchars;
  710.     char_u                *errmsg = NULL;
  711.     char_u                *buffer;
  712.     char_u                smallbuf[SBUFSIZE];
  713.     char_u                *backup_ext;
  714.     int                    bufsize;
  715.     long                 perm = -1;            /* file permissions */
  716.     int                    retval = OK;
  717.     int                    newfile = FALSE;    /* TRUE if file doesn't exist yet */
  718.     int                    msg_save = msg_scroll;
  719.     int                    overwriting;        /* TRUE if writing over original */
  720. #if defined(UNIX) || defined(__EMX__XX) /*XXX fix me sometime? */
  721.     struct stat            st_old;
  722.     int                    made_writable = FALSE;    /* 'w' bit has been set */
  723. #endif
  724. #ifdef AMIGA
  725.     BPTR                flock;
  726. #endif
  727.                                             /* writing everything */
  728.     int                    whole = (start == 1 && end == buf->b_ml.ml_line_count);
  729. #ifdef AUTOCMD
  730.     linenr_t            old_line_count = buf->b_ml.ml_line_count;
  731. #endif
  732.  
  733.     if (fname == NULL || *fname == NUL)        /* safety check */
  734.         return FAIL;
  735.  
  736.     /*
  737.      * If there is no file name yet, use the one for the written file.
  738.      * b_notedited is set to reflect this (in case the write fails).
  739.      * Don't do this when the write is for a filter command.
  740.      * Only do this when 'cpoptions' contains the 'f' flag.
  741.      */
  742.     if (reset_changed && whole && buf == curbuf &&
  743.                                    curbuf->b_filename == NULL && !filtering &&
  744.                                         vim_strchr(p_cpo, CPO_FNAMEW) != NULL)
  745.     {
  746.         if (setfname(fname, sfname, FALSE) == OK)
  747.             curbuf->b_notedited = TRUE;
  748.     }
  749.  
  750.     if (sfname == NULL)
  751.         sfname = fname;
  752.     /*
  753.      * For Unix: Use the short filename whenever possible.
  754.      * Avoids problems with networks and when directory names are changed.
  755.      * Don't do this for MS-DOS, a "cd" in a sub-shell may have moved us to
  756.      * another directory, which we don't detect
  757.      */
  758.     ffname = fname;                            /* remember full fname */
  759. #ifdef UNIX
  760.     if (!did_cd)
  761.         fname = sfname;
  762. #endif
  763.  
  764.         /* make sure we have a valid backup extension to use */
  765.     if (*p_bex == NUL)
  766.         backup_ext = (char_u *)".bak";
  767.     else
  768.         backup_ext = p_bex;
  769.  
  770.     if (buf->b_filename != NULL && fnamecmp(ffname, buf->b_filename) == 0)
  771.         overwriting = TRUE;
  772.     else
  773.         overwriting = FALSE;
  774.  
  775.     /*
  776.      * Disallow writing from .exrc and .vimrc in current directory for
  777.      * security reasons.
  778.      */
  779.     if (secure)
  780.     {
  781.         secure = 2;
  782.         emsg(e_curdir);
  783.         return FAIL;
  784.     }
  785.  
  786.     if (exiting)
  787.         settmode(0);                /* when exiting allow typahead now */
  788.  
  789.     ++no_wait_return;                /* don't wait for return yet */
  790.  
  791.     /*
  792.      * Set '[ and '] marks to the lines to be written.
  793.      */
  794.     buf->b_op_start.lnum = start;
  795.     buf->b_op_start.col = 0;
  796.     buf->b_op_end.lnum = end;
  797.     buf->b_op_end.col = 0;
  798.  
  799. #ifdef AUTOCMD
  800.     /*
  801.      * Apply PRE aucocommands.
  802.      * Careful: The autocommands may call buf_write() recursively!
  803.      */
  804.     save_buf = curbuf;
  805.     curbuf = buf;
  806.     curwin->w_buffer = buf;
  807.     if (append)
  808.         apply_autocmds(EVENT_FILEAPPENDPRE, fname, fname);
  809.     else if (filtering)
  810.         apply_autocmds(EVENT_FILTERWRITEPRE, NULL, fname);
  811.     else if (reset_changed && whole)
  812.         apply_autocmds(EVENT_BUFWRITEPRE, fname, fname);
  813.     else
  814.         apply_autocmds(EVENT_FILEWRITEPRE, fname, fname);
  815.     curbuf = save_buf;
  816.     curwin->w_buffer = save_buf;
  817.     
  818.     /*
  819.      * The autocommands may have changed the number of lines in the file.
  820.      * When writing the whole file, adjust the end.
  821.      * When writing part of the file, assume that the autocommands only
  822.      * changed the number of lines that are to be written (tricky!).
  823.      */
  824.     if (buf->b_ml.ml_line_count != old_line_count)
  825.     {
  826.         if (whole)                                            /* writing all */
  827.             end = buf->b_ml.ml_line_count;
  828.         else if (buf->b_ml.ml_line_count > old_line_count)    /* more lines */
  829.             end += buf->b_ml.ml_line_count - old_line_count;
  830.         else                                                /* less lines */
  831.         {
  832.             end -= old_line_count - buf->b_ml.ml_line_count;
  833.             if (end < start)
  834.             {
  835.                 --no_wait_return;
  836.                 EMSG("Autocommand changed number of lines in unexpected way");
  837.                 return FAIL;
  838.             }
  839.         }
  840.     }
  841. #endif
  842.  
  843.     if (shortmess(SHM_OVER))
  844.         msg_scroll = FALSE;            /* overwrite previous file message */
  845.     else
  846.         msg_scroll = TRUE;            /* don't overwrite previous file message */
  847.     if (!filtering)
  848.         filemess(buf,
  849. #ifndef UNIX
  850.                 did_cd ? fname : sfname,
  851. #else
  852.                 fname,
  853. #endif
  854.                     (char_u *)"");    /* show that we are busy */
  855.     msg_scroll = FALSE;                /* always overwrite the file message now */
  856.  
  857.     buffer = alloc(BUFSIZE);
  858.     if (buffer == NULL)                /* can't allocate big buffer, use small
  859.                                      * one (to be able to write when out of
  860.                                      * memory) */
  861.     {
  862.         buffer = smallbuf;
  863.         bufsize = SBUFSIZE;
  864.     }
  865.     else
  866.         bufsize = BUFSIZE;
  867.  
  868. #if defined(UNIX) && !defined(ARCHIE)
  869.         /* get information about original file (if there is one) */
  870.     st_old.st_dev = st_old.st_ino = 0;
  871.     if (stat((char *)fname, &st_old))
  872.         newfile = TRUE;
  873.     else
  874.     {
  875. #ifdef _POSIX_SOURCE
  876.         if (!S_ISREG(st_old.st_mode))              /* not a file */
  877. #else
  878.         if ((st_old.st_mode & S_IFMT) != S_IFREG)    /* not a file */
  879. #endif
  880.         {
  881. #ifdef _POSIX_SOURCE
  882.             if (S_ISDIR(st_old.st_mode))
  883. #else
  884.             if ((st_old.st_mode & S_IFMT) == S_IFDIR)
  885. #endif
  886.                 errmsg = (char_u *)"is a directory";
  887.             else
  888.                 errmsg = (char_u *)"is not a file";
  889.             goto fail;
  890.         }
  891.         if (buf->b_mtime_read != 0 &&
  892.                           buf->b_mtime_read != st_old.st_mtime && overwriting)
  893.         {
  894.             msg_scroll = TRUE;        /* don't overwrite messages here */
  895.             (void)set_highlight('e');    /* set highlight for error messages */
  896.             msg_highlight = TRUE;
  897.             /* don't use emsg() here, don't want to flush the buffers */
  898.             MSG("WARNING: The file has been changed since reading it!!!");
  899.             if (ask_yesno((char_u *)"Do you really want to write to it",
  900.                                                                  TRUE) == 'n')
  901.             {
  902.                 retval = FAIL;
  903.                 goto fail;
  904.             }
  905.             msg_scroll = FALSE;        /* always overwrite the file message now */
  906.         }
  907.         perm = st_old.st_mode;
  908.     }
  909. /*
  910.  * If we are not appending, the file exists, and the 'writebackup', 'backup'
  911.  * or 'patchmode' option is set, try to make a backup copy of the file.
  912.  */
  913.     if (!append && perm >= 0 && (p_wb || p_bk || *p_pm != NUL) &&
  914.                           (fd = open((char *)fname, O_RDONLY | O_EXTRA)) >= 0)
  915.     {
  916.         int                bfd, buflen;
  917.         char_u            copybuf[BUFSIZE + 1], *wp;
  918.         int                some_error = FALSE;
  919.         struct stat        st_new;
  920.         char_u            *dirp;
  921. #ifndef SHORT_FNAME
  922.         int                did_set_shortname;
  923. #endif
  924.  
  925.         /*
  926.          * Try to make the backup in each directory in the 'bdir' option.
  927.          *
  928.          * Unix semantics has it, that we may have a writable file, 
  929.          * that cannot be recreated with a simple open(..., O_CREAT, ) e.g:
  930.          *  - the directory is not writable, 
  931.          *  - the file may be a symbolic link, 
  932.          *  - the file may belong to another user/group, etc.
  933.          *
  934.          * For these reasons, the existing writable file must be truncated
  935.          * and reused. Creation of a backup COPY will be attempted.
  936.          */
  937.         dirp = p_bdir;
  938.         while (*dirp)
  939.         {
  940.             st_new.st_dev = st_new.st_ino = 0;
  941.             st_new.st_gid = 0;
  942.  
  943.             /*
  944.              * Isolate one directory name.
  945.              */
  946.             len = copy_option_part(&dirp, copybuf, BUFSIZE, ",");
  947.  
  948.             if (*copybuf == '.')            /* use same dir as file */
  949.                 STRCPY(copybuf, fname);
  950.             else                            /* use dir from 'bdir' option */
  951.             {
  952.                 if (!ispathsep(copybuf[len - 1]))
  953.                     copybuf[len++] = PATHSEP;
  954.                 STRCPY(copybuf + len, gettail(fname));
  955.             }
  956.  
  957. #ifndef SHORT_FNAME
  958.             did_set_shortname = FALSE;
  959. #endif
  960.  
  961.             /*
  962.              * May try twice if 'shortname' not set.
  963.              */
  964.             for (;;)
  965.             {
  966.                 /*
  967.                  * Make backup file name.
  968.                  */
  969.                 backup = buf_modname(buf, copybuf, backup_ext);
  970.                 if (backup == NULL)
  971.                 {
  972.                     some_error = TRUE;            /* out of memory */
  973.                     goto nobackup;
  974.                 }
  975.  
  976.                 /*
  977.                  * Check if backup file already exists.
  978.                  */
  979.                 if (!stat((char *)backup, &st_new))
  980.                 {
  981.                     /*
  982.                      * Check if backup file is same as original file.
  983.                      * May happen when modname gave the same file back.
  984.                      * E.g. silly link, or filename-length reached.
  985.                      * If we don't check here, we either ruin the file when
  986.                      * copying or erase it after writing. jw.
  987.                      */
  988.                     if (st_new.st_dev == st_old.st_dev &&
  989.                                            st_new.st_ino == st_old.st_ino)
  990.                     {
  991.                         vim_free(backup);
  992.                         backup = NULL;    /* there is no backup file to delete */
  993. #ifndef SHORT_FNAME
  994.                         /*
  995.                          * may try again with 'shortname' set
  996.                          */
  997.                         if (!(buf->b_shortname || buf->b_p_sn))
  998.                         {
  999.                             buf->b_shortname = TRUE;
  1000.                             did_set_shortname = TRUE;
  1001.                             continue;
  1002.                         }
  1003.                             /* setting shortname didn't help */
  1004.                         if (did_set_shortname)
  1005.                             buf->b_shortname = FALSE;
  1006. #endif
  1007.                         break;
  1008.                     }
  1009.  
  1010.                     /*
  1011.                      * If we are not going to keep the backup file, don't
  1012.                      * delete an existing one, try to use another name.
  1013.                      * Change one character, just before the extension.
  1014.                      */
  1015.                     if (!p_bk)
  1016.                     {
  1017.                         wp = backup + STRLEN(backup) - 1 - STRLEN(backup_ext);
  1018.                         if (wp < backup)        /* empty file name ??? */
  1019.                             wp = backup;
  1020.                         *wp = 'z';
  1021.                         while (*wp > 'a' && !stat((char *)backup, &st_new))
  1022.                             --*wp;
  1023.                         /* They all exist??? Must be something wrong. */
  1024.                         if (*wp == 'a')
  1025.                         {
  1026.                             vim_free(backup);
  1027.                             backup = NULL;
  1028.                         }
  1029.                     }
  1030.                 }
  1031.                 break;
  1032.             }
  1033.  
  1034.             /*
  1035.              * Try to create the backup file
  1036.              */
  1037.             if (backup != NULL)
  1038.             {
  1039.                 /* remove old backup, if present */
  1040.                 vim_remove(backup);
  1041.                 bfd = open((char *)backup, O_WRONLY | O_CREAT | O_EXTRA, 0666);
  1042.                 if (bfd < 0)
  1043.                 {
  1044.                     vim_free(backup);
  1045.                     backup = NULL;
  1046.                 }
  1047.                 else
  1048.                 {
  1049.                     /* set file protection same as original file, but strip
  1050.                      * s-bit */
  1051.                     (void)setperm(backup, perm & 0777);
  1052.  
  1053.                     /*
  1054.                      * Try to set the group of the backup same as the original
  1055.                      * file. If this fails, set the protection bits for the
  1056.                      * group same as the protection bits for others.
  1057.                      */
  1058.                     if (st_new.st_gid != st_old.st_gid &&
  1059. #ifdef HAVE_FCHOWN    /* sequent-ptx lacks fchown() */
  1060.                                           fchown(bfd, -1, st_old.st_gid) != 0)
  1061. #else
  1062.                                         chown(backup, -1, st_old.st_gid) != 0)
  1063. #endif
  1064.                         setperm(backup, (perm & 0707) | ((perm & 07) << 3));
  1065.  
  1066.                     /* copy the file. */
  1067.                     while ((buflen = read(fd, (char *)copybuf, BUFSIZE)) > 0)
  1068.                     {
  1069.                         if (write_buf(bfd, copybuf, buflen) == FAIL)
  1070.                         {
  1071.                             errmsg = (char_u *)"Can't write to backup file (use ! to override)";
  1072.                             break;
  1073.                         }
  1074.                     }
  1075.                     if (close(bfd) < 0 && errmsg == NULL)
  1076.                         errmsg = (char_u *)"Close error for backup file (use ! to override)";
  1077.                     if (buflen < 0)
  1078.                         errmsg = (char_u *)"Can't read file for backup (use ! to override)";
  1079.                     break;
  1080.                 }
  1081.             }
  1082.         }
  1083. nobackup:
  1084.         close(fd);                /* ignore errors for closing read file */
  1085.  
  1086.         if (backup == NULL && errmsg == NULL)
  1087.             errmsg = (char_u *)"Cannot create backup file (use ! to override)";
  1088.         /* ignore errors when forceit is TRUE */
  1089.         if ((some_error || errmsg) && !forceit)
  1090.         {
  1091.             retval = FAIL;
  1092.             goto fail;
  1093.         }
  1094.         errmsg = NULL;
  1095.     }
  1096.     /* When using ":w!" and the file was read-only: make it writable */
  1097.     if (forceit && (st_old.st_uid == getuid()) && perm >= 0 && !(perm & 0200))
  1098.      {
  1099.         perm |= 0200;    
  1100.         (void)setperm(fname, perm);
  1101.         made_writable = TRUE;
  1102.     }
  1103.  
  1104. #else /* end of UNIX, start of the rest */
  1105.  
  1106. /*
  1107.  * If we are not appending, the file exists, and the 'writebackup' or
  1108.  * 'backup' option is set, make a backup.
  1109.  * Do not make any backup, if "writebackup" and "backup" are 
  1110.  * both switched off. This helps when editing large files on
  1111.  * almost-full disks. (jw)
  1112.  */
  1113.     perm = getperm(fname);
  1114.     if (perm < 0)
  1115.         newfile = TRUE;
  1116.     else if (mch_isdir(fname))
  1117.     {
  1118.         errmsg = (char_u *)"is a directory";
  1119.         goto fail;
  1120.     }
  1121.     if (!append && perm >= 0 && (p_wb || p_bk || *p_pm != NUL))
  1122.     {
  1123.         char_u            *dirp;
  1124.         char_u            *p;
  1125.  
  1126.         /*
  1127.          * Form the backup file name - change path/fo.o.h to path/fo.o.h.bak
  1128.          * Try all directories in 'backupdir', first one that works is used.
  1129.          */
  1130.         dirp = p_bdir;
  1131.         while (*dirp)
  1132.         {
  1133.             /*
  1134.              * Isolate one directory name.
  1135.              */
  1136.             len = copy_option_part(&dirp, IObuff, IOSIZE, ",");
  1137.  
  1138. #ifdef VMS
  1139.             if (!memcmp(IObuff, "sys$disk:", 9))
  1140. #else
  1141.             if (*IObuff == '.')            /* use same dir as file */
  1142. #endif
  1143.                 backup = buf_modname(buf, fname, backup_ext);
  1144.             else                        /* use dir from 'bdir' option */
  1145.             {
  1146.                 if (!ispathsep(IObuff[len - 1]))
  1147.                     IObuff[len++] = PATHSEP;
  1148.                 STRCPY(IObuff + len, gettail(fname));
  1149.                 backup = buf_modname(buf, IObuff, backup_ext);
  1150.             }
  1151.             if (backup != NULL)
  1152.             {
  1153.                 /*
  1154.                  * If we are not going to keep the backup file, don't
  1155.                  * delete an existing one, try to use another name.
  1156.                  * Change one character, just before the extension.
  1157.                  */
  1158.                 if (!p_bk && getperm(backup) >= 0)
  1159.                 {
  1160.                     p = backup + STRLEN(backup) - 1 - STRLEN(backup_ext);
  1161.                     if (p < backup)        /* empty file name ??? */
  1162.                         p = backup;
  1163.                     *p = 'z';
  1164.                     while (*p > 'a' && getperm(backup) >= 0)
  1165.                         --*p;
  1166.                     /* They all exist??? Must be something wrong! */
  1167.                     if (*p == 'a')
  1168.                     {
  1169.                         vim_free(backup);
  1170.                         backup = NULL;
  1171.                     }
  1172.                 }
  1173.             }
  1174.             if (backup != NULL)
  1175.             {
  1176.  
  1177.                 /*
  1178.                  * Delete any existing backup and move the current version to
  1179.                  * the backup.  For safety, we don't remove the backup until
  1180.                  * the write has finished successfully. And if the 'backup'
  1181.                  * option is set, leave it around.
  1182.                  */
  1183. #ifdef AMIGA
  1184.                 /*
  1185.                  * With MSDOS-compatible filesystems (crossdos, messydos) it is
  1186.                  * possible that the name of the backup file is the same as the
  1187.                  * original file. To avoid the chance of accidently deleting the
  1188.                  * original file (horror!) we lock it during the remove.
  1189.                  * This should not happen with ":w", because startscript()
  1190.                  * should detect this problem and set buf->b_shortname,
  1191.                  * causing modname to return a correct ".bak" filename. This
  1192.                  * problem does exist with ":w filename", but then the
  1193.                  * original file will be somewhere else so the backup isn't
  1194.                  * really important. If autoscripting is off the rename may
  1195.                  * fail.
  1196.                  */
  1197.                 flock = Lock((UBYTE *)fname, (long)ACCESS_READ);
  1198. #endif
  1199.                 vim_remove(backup);
  1200. #ifdef AMIGA
  1201.                 if (flock)
  1202.                     UnLock(flock);
  1203. #endif
  1204.                 /*
  1205.                  * If the renaming of the original file to the backup file
  1206.                  * works, quit here.
  1207.                  */
  1208.                 if (vim_rename(fname, backup) == 0)
  1209.                     break;
  1210.  
  1211.                 vim_free(backup);    /* don't do the rename below */
  1212.                 backup = NULL;
  1213.             }
  1214.         }
  1215.         if (backup == NULL && !forceit)
  1216.         {
  1217.             errmsg = (char_u *)"Can't make backup file (use ! to override)";
  1218.             goto fail;
  1219.         }
  1220.     }
  1221. #endif /* UNIX */
  1222.  
  1223.     /* When using ":w!" and writing to the current file, readonly makes no
  1224.      * sense, reset it */
  1225.     if (forceit && overwriting)
  1226.         buf->b_p_ro = FALSE;
  1227.  
  1228.     /*
  1229.      * If the original file is being overwritten, there is a small chance that
  1230.      * we crash in the middle of writing. Therefore the file is preserved now.
  1231.      * This makes all block numbers positive so that recovery does not need
  1232.      * the original file.
  1233.      * Don't do this if there is a backup file and we are exiting.
  1234.      */
  1235.     if (reset_changed && !newfile && !otherfile(ffname) &&
  1236.                                             !(exiting && backup != NULL))
  1237.         ml_preserve(buf, FALSE);
  1238.  
  1239.     /* 
  1240.      * We may try to open the file twice: If we can't write to the
  1241.      * file and forceit is TRUE we delete the existing file and try to create
  1242.      * a new one. If this still fails we may have lost the original file!
  1243.      * (this may happen when the user reached his quotum for number of files).
  1244.      * Appending will fail if the file does not exist and forceit is FALSE.
  1245.      */
  1246.     while ((fd = open((char *)fname, O_WRONLY | O_EXTRA | (append ?
  1247.                     (forceit ? (O_APPEND | O_CREAT) : O_APPEND) :
  1248.                     (O_CREAT | O_TRUNC)), 0666)) < 0)
  1249.      {
  1250.         /*
  1251.          * A forced write will try to create a new file if the old one is
  1252.          * still readonly. This may also happen when the directory is
  1253.          * read-only. In that case the vim_remove() will fail.
  1254.          */
  1255.         if (!errmsg)
  1256.         {
  1257.             errmsg = (char_u *)"Can't open file for writing";
  1258.             if (forceit)
  1259.             {
  1260. #ifdef UNIX
  1261.                 /* we write to the file, thus it should be marked
  1262.                                                     writable after all */
  1263.                 perm |= 0200;        
  1264.                 made_writable = TRUE;
  1265.                 if (st_old.st_uid != getuid() || st_old.st_gid != getgid())
  1266.                     perm &= 0777;
  1267. #endif /* UNIX */
  1268.                 if (!append)        /* don't remove when appending */
  1269.                     vim_remove(fname);
  1270.                 continue;
  1271.             }
  1272.         }
  1273. /*
  1274.  * If we failed to open the file, we don't need a backup. Throw it away.
  1275.  * If we moved or removed the original file try to put the backup in its place.
  1276.  */
  1277.          if (backup != NULL)
  1278.         {
  1279. #ifdef UNIX
  1280.             struct stat st;
  1281.  
  1282.             /*
  1283.              * There is a small chance that we removed the original, try
  1284.              * to move the copy in its place.
  1285.              * This may not work if the vim_rename() fails.
  1286.              * In that case we leave the copy around.
  1287.              */
  1288.                                          /* file does not exist */
  1289.             if (stat((char *)fname, &st) < 0)
  1290.                                         /* put the copy in its place */
  1291.                 vim_rename(backup, fname);
  1292.                                         /* original file does exist */
  1293.             if (stat((char *)fname, &st) >= 0)
  1294.                 vim_remove(backup);    /* throw away the copy */
  1295. #else
  1296.                                         /* try to put the original file back */
  1297.              vim_rename(backup, fname);
  1298. #endif
  1299.         }
  1300.          goto fail;
  1301.      }
  1302.     errmsg = NULL;
  1303.  
  1304.     if (end > buf->b_ml.ml_line_count)
  1305.         end = buf->b_ml.ml_line_count;
  1306.     len = 0;
  1307.     s = buffer;
  1308.     nchars = 0;
  1309.     if (buf->b_ml.ml_flags & ML_EMPTY)
  1310.         start = end + 1;
  1311.     for (lnum = start; lnum <= end; ++lnum)
  1312.     {
  1313.         /*
  1314.          * The next while loop is done once for each character written.
  1315.          * Keep it fast!
  1316.          */
  1317.         ptr = ml_get_buf(buf, lnum, FALSE) - 1;
  1318.         while ((c = *++ptr) != NUL)
  1319.         {
  1320.             if (c == NL)
  1321.                 *s = NUL;        /* replace newlines with NULs */
  1322.             else
  1323.                 *s = c;
  1324.             ++s;
  1325.             if (++len != bufsize)
  1326.                 continue;
  1327.             if (write_buf(fd, buffer, bufsize) == FAIL)
  1328.             {
  1329.                 end = 0;                /* write error: break loop */
  1330.                 break;
  1331.             }
  1332.             nchars += bufsize;
  1333.             s = buffer;
  1334.             len = 0;
  1335.         }
  1336.             /* write failed or last line has no EOL: stop here */
  1337.         if (end == 0 || (lnum == end && buf->b_p_bin &&
  1338.                                                 (lnum == write_no_eol_lnum ||
  1339.                          (lnum == buf->b_ml.ml_line_count && !buf->b_p_eol))))
  1340.             break;
  1341.         if (buf->b_p_tx)        /* write CR-NL */
  1342.         {
  1343.             *s = CR;
  1344.             ++s;
  1345.             if (++len == bufsize)
  1346.             {
  1347.                 if (write_buf(fd, buffer, bufsize) == FAIL)
  1348.                 {
  1349.                     end = 0;                /* write error: break loop */
  1350.                     break;
  1351.                 }
  1352.                 nchars += bufsize;
  1353.                 s = buffer;
  1354.                 len = 0;
  1355.             }
  1356.         }
  1357.         *s = NL;
  1358.         ++s;
  1359.         if (++len == bufsize && end)
  1360.         {
  1361.             if (write_buf(fd, buffer, bufsize) == FAIL)
  1362.             {
  1363.                 end = 0;                /* write error: break loop */
  1364.                 break;
  1365.             }
  1366.             nchars += bufsize;
  1367.             s = buffer;
  1368.             len = 0;
  1369.         }
  1370.     }
  1371.     if (len && end)
  1372.     {
  1373.         if (write_buf(fd, buffer, len) == FAIL)
  1374.             end = 0;                /* write error */
  1375.         nchars += len;
  1376.     }
  1377.  
  1378.     if (close(fd) != 0)
  1379.     {
  1380.         errmsg = (char_u *)"Close failed";
  1381.         goto fail;
  1382.     }
  1383. #ifdef UNIX
  1384.     if (made_writable)
  1385.         perm &= ~0200;            /* reset 'w' bit for security reasons */
  1386. #endif
  1387.     if (perm >= 0)
  1388.         (void)setperm(fname, perm);    /* set permissions of new file same as old file */
  1389.  
  1390.     if (end == 0)
  1391.     {
  1392.         errmsg = (char_u *)"write error (file system full?)";
  1393.         /*
  1394.          * If we have a backup file, try to put it in place of the new file,
  1395.          * because it is probably corrupt. This avoids loosing the original
  1396.          * file when trying to make a backup when writing the file a second
  1397.          * time.
  1398.          * For unix this means copying the backup over the new file.
  1399.          * For others this means renaming the backup file.
  1400.          * If this is OK, don't give the extra warning message.
  1401.          */
  1402.         if (backup != NULL)
  1403.         {
  1404. #ifdef UNIX
  1405.             char_u        copybuf[BUFSIZE + 1];
  1406.             int            bfd, buflen;
  1407.  
  1408.             if ((bfd = open((char *)backup, O_RDONLY | O_EXTRA)) >= 0)
  1409.             {
  1410.                 if ((fd = open((char *)fname,
  1411.                           O_WRONLY | O_CREAT | O_TRUNC | O_EXTRA, 0666)) >= 0)
  1412.                 {
  1413.                     /* copy the file. */
  1414.                     while ((buflen = read(bfd, (char *)copybuf, BUFSIZE)) > 0)
  1415.                         if (write_buf(fd, copybuf, buflen) == FAIL)
  1416.                             break;
  1417.                     if (close(fd) >= 0 && buflen == 0)    /* success */
  1418.                         end = 1;
  1419.                 }
  1420.                 close(bfd);        /* ignore errors for closing read file */
  1421.             }
  1422. #else
  1423.             if (vim_rename(backup, fname) == 0)
  1424.                 end = 1;
  1425. #endif
  1426.         }
  1427.         goto fail;
  1428.     }
  1429.  
  1430.     lnum -= start;            /* compute number of written lines */
  1431.     --no_wait_return;        /* may wait for return now */
  1432.  
  1433. #ifndef UNIX
  1434.     /* use shortname now, for the messages */
  1435.     if (!did_cd)
  1436.         fname = sfname;
  1437. #endif
  1438.     if (!filtering)
  1439.     {
  1440.         msg_add_fname(buf, fname);        /* put fname in IObuff with quotes */
  1441.         c = FALSE;
  1442.         if (newfile)
  1443.         {
  1444.             STRCAT(IObuff, shortmess(SHM_NEW) ? "[New]" : "[New File]");
  1445.             c = TRUE;
  1446.         }
  1447.         if (msg_add_textmode(buf->b_p_tx))        /* may add [textmode] */
  1448.             c = TRUE;
  1449.         msg_add_lines(c, (long)lnum, nchars);    /* add line/char count */
  1450.         if (!shortmess(SHM_WRITE))
  1451.             STRCAT(IObuff, shortmess(SHM_WRI) ? " [w]" : " written");
  1452.  
  1453.         msg_trunc(IObuff);
  1454.     }
  1455.  
  1456.     if (reset_changed && whole)            /* when written everything */
  1457.     {
  1458.         UNCHANGED(buf);
  1459.         u_unchanged(buf);
  1460.     }
  1461.  
  1462.     /*
  1463.      * If written to the current file, update the timestamp of the swap file
  1464.      * and reset the 'notedited' flag. Also sets buf->b_mtime.
  1465.      */
  1466.     if (!exiting && overwriting)
  1467.     {
  1468.         ml_timestamp(buf);
  1469.         buf->b_notedited = FALSE;
  1470.     }
  1471.  
  1472.     /*
  1473.      * If we kept a backup until now, and we are in patch mode, then we make
  1474.      * the backup file our 'original' file.
  1475.      */
  1476.     if (*p_pm)
  1477.     {
  1478.         char *org = (char *)buf_modname(buf, fname, p_pm);
  1479.  
  1480.         if (backup != NULL)
  1481.         {
  1482.             struct stat st;
  1483.  
  1484.             /*
  1485.              * If the original file does not exist yet
  1486.              * the current backup file becomes the original file
  1487.              */
  1488.             if (org == NULL)
  1489.                 EMSG("patchmode: can't save original file");
  1490.             else if (stat(org, &st) < 0)
  1491.             {
  1492.                 vim_rename(backup, (char_u *)org);
  1493.                 vim_free(backup);            /* don't delete the file */
  1494.                 backup = NULL;
  1495.             }
  1496.         }
  1497.         /*
  1498.          * If there is no backup file, remember that a (new) file was
  1499.          * created.
  1500.          */
  1501.         else
  1502.         {
  1503.             int empty_fd;
  1504.  
  1505.             if (org == NULL || (empty_fd =
  1506.                                       open(org, O_CREAT | O_EXTRA, 0666)) < 0)
  1507.               EMSG("patchmode: can't touch empty original file");
  1508.             else
  1509.               close(empty_fd);
  1510.         }
  1511.         if (org != NULL)
  1512.         {
  1513.             setperm((char_u *)org, getperm(fname) & 0777);
  1514.             vim_free(org);
  1515.         }
  1516.     }
  1517.  
  1518.     /*
  1519.      * Remove the backup unless 'backup' option is set
  1520.      */
  1521.     if (!p_bk && backup != NULL && vim_remove(backup) != 0)
  1522.         EMSG("Can't delete backup file");
  1523.     
  1524.     goto nofail;
  1525.  
  1526. fail:
  1527.     --no_wait_return;        /* may wait for return now */
  1528. nofail:
  1529.  
  1530.     vim_free(backup);
  1531.     if (buffer != smallbuf)
  1532.         vim_free(buffer);
  1533.  
  1534.     if (errmsg != NULL)
  1535.     {
  1536.         /* can't use emsg() here, do something alike */
  1537.         if (p_eb)
  1538.             beep_flush();            /* also includes flush_buffers() */
  1539.         else
  1540.             flush_buffers(FALSE);    /* flush internal buffers */
  1541.         (void)set_highlight('e');    /* set highlight mode for error messages */
  1542.         start_highlight();
  1543.         filemess(buf,
  1544. #ifndef UNIX
  1545.                         did_cd ? fname : sfname,
  1546. #else
  1547.                         fname,
  1548. #endif
  1549.                                                     errmsg);
  1550.         retval = FAIL;
  1551.         if (end == 0)
  1552.         {
  1553.             MSG_OUTSTR("\nWARNING: Original file may be lost or damaged\n");
  1554.             MSG_OUTSTR("don't quit the editor until the file is sucessfully written!");
  1555.         }
  1556.     }
  1557.     msg_scroll = msg_save;
  1558.  
  1559. #ifdef AUTOCMD
  1560.     /*
  1561.      * Apply POST aucocommands.
  1562.      * Careful: The autocommands may call buf_write() recursively!
  1563.      */
  1564.     save_buf = curbuf;
  1565.     curbuf = buf;
  1566.     curwin->w_buffer = buf;
  1567.     if (append)
  1568.         apply_autocmds(EVENT_FILEAPPENDPOST, fname, fname);
  1569.     else if (filtering)
  1570.         apply_autocmds(EVENT_FILTERWRITEPOST, NULL, fname);
  1571.     else if (reset_changed && whole)
  1572.         apply_autocmds(EVENT_BUFWRITEPOST, fname, fname);
  1573.     else
  1574.         apply_autocmds(EVENT_FILEWRITEPOST, fname, fname);
  1575.     curbuf = save_buf;
  1576.     curwin->w_buffer = save_buf;
  1577. #endif
  1578.  
  1579.     return retval;
  1580. }
  1581.  
  1582. /*
  1583.  * Put file name into IObuff with quotes.
  1584.  */
  1585.     static void
  1586. msg_add_fname(buf, fname)
  1587.     BUF        *buf;
  1588.     char_u    *fname;
  1589. {
  1590.         /* careful: home_replace calls vim_getenv(), which also uses IObuff! */
  1591.     home_replace(buf, fname, IObuff + 1, IOSIZE - 1);
  1592.     IObuff[0] = '"';
  1593.     STRCAT(IObuff, "\" ");
  1594. }
  1595.  
  1596. /*
  1597.  * Append message for text mode to IObuff.
  1598.  * Return TRUE if something appended.
  1599.  */
  1600.     static int
  1601. msg_add_textmode(textmode)
  1602.     int        textmode;
  1603. {
  1604. #ifdef USE_CRNL
  1605.     if (!textmode)
  1606.     {
  1607.         STRCAT(IObuff, shortmess(SHM_TEXT) ? "[notx]" : "[notextmode]");
  1608.         return TRUE;
  1609.     }
  1610. #else
  1611.     if (textmode)
  1612.     {
  1613.         STRCAT(IObuff, shortmess(SHM_TEXT) ? "[tx]" : "[textmode]");
  1614.         return TRUE;
  1615.     }
  1616. #endif
  1617.     return FALSE;
  1618. }
  1619.  
  1620. /*
  1621.  * Append line and character count to IObuff.
  1622.  */
  1623.     static void
  1624. msg_add_lines(insert_space, lnum, nchars)
  1625.     int        insert_space;
  1626.     long    lnum;
  1627.     long    nchars;
  1628. {
  1629.     char_u    *p;
  1630.  
  1631.     p = IObuff + STRLEN(IObuff);
  1632.  
  1633.     if (insert_space)
  1634.         *p++ = ' ';
  1635.     if (shortmess(SHM_LINES))
  1636.         sprintf((char *)p, "%ldL, %ldC", lnum, nchars);
  1637.     else
  1638.         sprintf((char *)p, "%ld line%s, %ld character%s",
  1639.             lnum, plural(lnum),
  1640.             nchars, plural(nchars));
  1641. }
  1642.  
  1643. /*
  1644.  * write_buf: call write() to write a buffer
  1645.  *
  1646.  * return FAIL for failure, OK otherwise
  1647.  */
  1648.     static int
  1649. write_buf(fd, buf, len)
  1650.     int        fd;
  1651.     char_u    *buf;
  1652.     int        len;
  1653. {
  1654.     int        wlen;
  1655.  
  1656.     while (len)
  1657.     {
  1658.         wlen = write(fd, (char *)buf, (size_t)len);
  1659.         if (wlen <= 0)                /* error! */
  1660.             return FAIL;
  1661.         len -= wlen;
  1662.         buf += wlen;
  1663.     }
  1664.     return OK;
  1665. }
  1666.  
  1667. /*
  1668.  * add extention to filename - change path/fo.o.h to path/fo.o.h.ext or
  1669.  * fo_o_h.ext for MSDOS or when shortname option set.
  1670.  *
  1671.  * Assumed that fname is a valid name found in the filesystem we assure that
  1672.  * the return value is a different name and ends in 'ext'.
  1673.  * "ext" MUST be at most 4 characters long if it starts with a dot, 3
  1674.  * characters otherwise.
  1675.  * Space for the returned name is allocated, must be freed later.
  1676.  */
  1677.  
  1678.     char_u *
  1679. modname(fname, ext)
  1680.     char_u *fname, *ext;
  1681. {
  1682.     return buf_modname(curbuf, fname, ext);
  1683. }
  1684.  
  1685.     char_u *
  1686. buf_modname(buf, fname, ext)
  1687.     BUF        *buf;
  1688.     char_u *fname, *ext;
  1689. {
  1690.     char_u                *retval;
  1691.     register char_u     *s;
  1692.     register char_u        *e;
  1693.     register char_u        *ptr;
  1694.     register int        fnamelen, extlen;
  1695.  
  1696.     extlen = STRLEN(ext);
  1697.  
  1698.     /*
  1699.      * if there is no filename we must get the name of the current directory
  1700.      * (we need the full path in case :cd is used)
  1701.      */
  1702.     if (fname == NULL || *fname == NUL)
  1703.     {
  1704.         retval = alloc((unsigned)(MAXPATHL + extlen + 3));
  1705.         if (retval == NULL)
  1706.             return NULL;
  1707.         if (mch_dirname(retval, MAXPATHL) == FAIL ||
  1708.                                              (fnamelen = STRLEN(retval)) == 0)
  1709.         {
  1710.             vim_free(retval);
  1711.             return NULL;
  1712.         }
  1713.         if (!ispathsep(retval[fnamelen - 1]))
  1714.         {
  1715.             retval[fnamelen++] = PATHSEP;
  1716.             retval[fnamelen] = NUL;
  1717.         }
  1718.     }
  1719.     else
  1720.     {
  1721.         fnamelen = STRLEN(fname);
  1722.         retval = alloc((unsigned)(fnamelen + extlen + 2));
  1723.         if (retval == NULL)
  1724.             return NULL;
  1725.         STRCPY(retval, fname);
  1726.     }
  1727.  
  1728.     /*
  1729.      * search backwards until we hit a '/', '\' or ':' replacing all '.'
  1730.      * by '_' for MSDOS or when shortname option set and ext starts with a dot.
  1731.      * Then truncate what is after the '/', '\' or ':' to 8 characters for
  1732.      * MSDOS and 26 characters for AMIGA, a lot more for UNIX.
  1733.      */
  1734.     for (ptr = retval + fnamelen; ptr >= retval; ptr--)
  1735.     {
  1736.         if (*ext == '.'
  1737. #ifdef USE_LONG_FNAME
  1738.                     && (!USE_LONG_FNAME || buf->b_p_sn || buf->b_shortname)
  1739. #else
  1740. # ifndef SHORT_FNAME
  1741.                     && (buf->b_p_sn || buf->b_shortname)
  1742. # endif
  1743. #endif
  1744.                                                                 )
  1745.             if (*ptr == '.')    /* replace '.' by '_' */
  1746.                 *ptr = '_';
  1747.         if (ispathsep(*ptr))
  1748.             break;
  1749.     }
  1750.     ptr++;
  1751.  
  1752.     /* the filename has at most BASENAMELEN characters. */
  1753. #ifndef SHORT_FNAME
  1754.     if (STRLEN(ptr) > (unsigned)BASENAMELEN)
  1755.         ptr[BASENAMELEN] = '\0';
  1756. #endif
  1757.  
  1758.     s = ptr + STRLEN(ptr);
  1759.  
  1760.     /*
  1761.      * For 8.3 filenames we may have to reduce the length.
  1762.      */
  1763. #ifdef USE_LONG_FNAME
  1764.     if (!USE_LONG_FNAME || buf->b_p_sn || buf->b_shortname)
  1765. #else
  1766. # ifndef SHORT_FNAME
  1767.     if (buf->b_p_sn || buf->b_shortname)
  1768. # endif
  1769. #endif
  1770.     {
  1771.         /*
  1772.          * If there is no file name, and the extension starts with '.', put a
  1773.          * '_' before the dot, because just ".ext" is invalid.
  1774.          */
  1775.         if (fname == NULL || *fname == NUL)
  1776.         {
  1777.             if (*ext == '.')
  1778.                 *s++ = '_';
  1779.         }
  1780.         /*
  1781.          * If the extension starts with '.', truncate the base name at 8
  1782.          * characters
  1783.          */
  1784.         else if (*ext == '.')
  1785.         {
  1786.             if (s - ptr > (size_t)8)
  1787.             {
  1788.                 s = ptr + 8;
  1789.                 *s = '\0';
  1790.             }
  1791.         }
  1792.         /*
  1793.          * If the extension doesn't start with '.', and the file name
  1794.          * doesn't have an extension yet, append a '.'
  1795.          */
  1796.         else if ((e = vim_strchr(ptr, '.')) == NULL)
  1797.             *s++ = '.';
  1798.         /*
  1799.          * If If the extension doesn't start with '.', and there already is an
  1800.          * extension, it may need to be tructated
  1801.          */
  1802.         else if ((int)STRLEN(e) + extlen > 4)
  1803.             s = e + 4 - extlen;
  1804.     }
  1805. #ifdef OS2
  1806.     /*
  1807.      * If there is no file name, and the extension starts with '.', put a
  1808.      * '_' before the dot, because just ".ext" may be invalid if it's on a
  1809.      * FAT partition, and on HPFS it doesn't matter.
  1810.      */
  1811.     else if ((fname == NULL || *fname == NUL) && *ext == '.')
  1812.         *s++ = '_';
  1813. #endif
  1814.  
  1815.     /*
  1816.      * Append the extention.
  1817.      * ext can start with '.' and cannot exceed 3 more characters.
  1818.      */
  1819.     STRCPY(s, ext);
  1820.  
  1821.     /*
  1822.      * Check that, after appending the extension, the file name is really
  1823.      * different.
  1824.      */
  1825.     if (fname != NULL && STRCMP(fname, retval) == 0)
  1826.     {
  1827.         /* we search for a character that can be replaced by '_' */
  1828.         while (--s >= ptr)
  1829.         {
  1830.             if (*s != '_')
  1831.             {
  1832.                 *s = '_';
  1833.                 break;
  1834.             }
  1835.         }
  1836.         if (s < ptr)    /* fname was "________.<ext>" how tricky! */
  1837.             *ptr = 'v';
  1838.     }
  1839.     return retval;
  1840. }
  1841.  
  1842. /* vim_fgets();
  1843.  *
  1844.  * Like fgets(), but if the file line is too long, it is truncated and the
  1845.  * rest of the line is thrown away.  Returns TRUE for end-of-file.
  1846.  * Note: do not pass IObuff as the buffer since this is used to read and
  1847.  * discard the extra part of any long lines.
  1848.  */
  1849.     int
  1850. vim_fgets(buf, size, fp)
  1851.     char_u        *buf;
  1852.     int            size;
  1853.     FILE        *fp;
  1854. {
  1855.     char *eof;
  1856.  
  1857.     buf[size - 2] = NUL;
  1858.     eof = fgets((char *)buf, size, fp);
  1859.     if (buf[size - 2] != NUL && buf[size - 2] != '\n')
  1860.     {
  1861.         buf[size - 1] = NUL;        /* Truncate the line */
  1862.  
  1863.         /* Now throw away the rest of the line: */
  1864.         do
  1865.         {
  1866.             IObuff[IOSIZE - 2] = NUL;
  1867.             fgets((char *)IObuff, IOSIZE, fp);
  1868.         } while (IObuff[IOSIZE - 2] != NUL && IObuff[IOSIZE - 2] != '\n');
  1869.     }
  1870.     return (eof == NULL);
  1871. }
  1872.  
  1873. /*
  1874.  * rename() only works if both files are on the same file system, this
  1875.  * function will (attempts to?) copy the file across if rename fails -- webb
  1876.  * Return -1 for failure, 0 for success.
  1877.  */
  1878.     int
  1879. vim_rename(from, to)
  1880.     char_u *from;
  1881.     char_u *to;
  1882. {
  1883.     int        fd_in;
  1884.     int        fd_out;
  1885.     int        n;
  1886.     char     *errmsg = NULL;
  1887.  
  1888.     /*
  1889.      * First delete the "to" file, this is required on some systems to make
  1890.      * the rename() work, on other systems it makes sure that we don't have
  1891.      * two files when the rename() fails.
  1892.      */
  1893.     vim_remove(to);
  1894.  
  1895.     /*
  1896.      * First try a normal rename, return if it works.
  1897.      */
  1898.     if (rename((char *)from, (char *)to) == 0)
  1899.         return 0;
  1900.  
  1901.     /*
  1902.      * Rename() failed, try copying the file.
  1903.      */
  1904.     fd_in = open((char *)from, O_RDONLY | O_EXTRA);
  1905.     if (fd_in == -1)
  1906.         return -1;
  1907.     fd_out = open((char *)to, O_CREAT | O_TRUNC | O_WRONLY | O_EXTRA, 0666);
  1908.     if (fd_out == -1)
  1909.     {
  1910.         close(fd_in);
  1911.         return -1;
  1912.     }
  1913.     while ((n = read(fd_in, (char *)IObuff, (size_t)IOSIZE)) > 0)
  1914.         if (write(fd_out, (char *)IObuff, (size_t)n) != n)
  1915.         {
  1916.             errmsg = "writing to";
  1917.             break;
  1918.         }
  1919.     close(fd_in);
  1920.     if (close(fd_out) < 0)
  1921.         errmsg = "closing";
  1922.     if (n < 0)
  1923.     {
  1924.         errmsg = "reading";
  1925.         to = from;
  1926.     }
  1927.     if (errmsg != NULL)
  1928.     {
  1929.         sprintf((char *)IObuff, "Error %s '%s'", errmsg, to);
  1930.         emsg(IObuff);
  1931.         return -1;
  1932.     }
  1933.     vim_remove(from);
  1934.     return 0;
  1935. }
  1936.  
  1937. /*
  1938.  * Check if any not hidden buffer has been changed.
  1939.  * Postpone the check if there are characters in the stuff buffer, a global
  1940.  * command is being executed, a mapping is being executed or an autocommand is
  1941.  * busy.
  1942.  */
  1943.     void
  1944. check_timestamps()
  1945. {
  1946.     BUF        *buf;
  1947.  
  1948.     if (!stuff_empty() || global_busy || !typebuf_typed()
  1949. #ifdef AUTOCMD
  1950.                         || autocmd_busy
  1951. #endif
  1952.                                         )
  1953.         need_check_timestamps = TRUE;            /* check later */
  1954.     else
  1955.     {
  1956.         ++no_wait_return;
  1957.         for (buf = firstbuf; buf != NULL; buf = buf->b_next)
  1958.             buf_check_timestamp(buf);
  1959.         --no_wait_return;
  1960.         need_check_timestamps = FALSE;
  1961.     }
  1962. }
  1963.  
  1964. /*
  1965.  * Check if buffer "buf" has been changed.
  1966.  */
  1967.     void
  1968. buf_check_timestamp(buf)
  1969.     BUF        *buf;
  1970. {
  1971.     struct stat        st;
  1972.     char_u            *path;
  1973.  
  1974.     if (    buf->b_filename != NULL &&
  1975.             buf->b_ml.ml_mfp != NULL &&
  1976.             !buf->b_notedited &&
  1977.             buf->b_mtime != 0 &&
  1978.             stat((char *)buf->b_filename, &st) >= 0 &&
  1979.             buf->b_mtime != st.st_mtime)
  1980.     {
  1981.         path = home_replace_save(buf, buf->b_xfilename);
  1982.         if (path != NULL)
  1983.         {
  1984.             EMSG2("Warning: File \"%s\" has changed since editing started",
  1985.                                                                 path);
  1986.             buf->b_mtime = st.st_mtime;
  1987.             vim_free(path);
  1988.         }
  1989.     }
  1990. }
  1991.